package jp.sourceforge.akjrcp.audiotools;

import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;

import jp.sourceforge.akjrcp.ui.draw2d.WaveFormFigureCanvas;
import jp.sourceforge.akjrcp.ui.draw2d.WaveFormFigureCanvas.TimeSelection;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.swt.widgets.Shell;
import org.jpn.xucker.commons.audio.AudioListener;
import org.jpn.xucker.commons.audio.AudioStopper;
import org.jpn.xucker.commons.audio.JavaSoundAudioPlayer;
import org.jpn.xucker.commons.audio.WaveUtils;



public class WaveFormFigureCanvasAudioPlayer implements AudioStopper{
	public static Log log=LogFactory.getLog(WaveFormFigureCanvasAudioPlayer.class);
	private WaveFormFigureCanvas waveFormFigureCanvas;
	private File audioFile;
	private TimeSelection selection;
	private long duration;
	private JavaSoundAudioPlayer player;
	private boolean playMoveSelection;
	private boolean stopped=true;	//if continue playing 
	private Shell shell;
	public WaveFormFigureCanvasAudioPlayer(Shell shell,WaveFormFigureCanvas waveFormFigureCanvas){
		this.shell=shell;
		this.waveFormFigureCanvas=waveFormFigureCanvas;
	}
	
	public void play(){
	     
	     if(audioFile==null){
	    	log.info("audioFile is null");
	        stop();
	        return;
	     	}
	     
	     if(isPlayingAudio() || audioFile==null){
		    	log.info("playing");
		        stop();
		        return;
		     	}
	     
	     
	     AudioFormat format=null;
       try {
    	   format = WaveUtils.getAudioFormat(audioFile);
       } catch (UnsupportedAudioFileException e1) {
           // TODO Auto-generated catch block
           e1.printStackTrace();
       } catch (IOException e1) {
           // TODO Auto-generated catch block
           e1.printStackTrace();
       }
           selection = waveFormFigureCanvas.getSelection();
          // log.info("selection:"+selection);
           
           //not selected so start at location.
           if(selection==null || (selection.getStart()==0 && selection.getEnd()==0)){
               selection=new TimeSelection(waveFormFigureCanvas.getCurrentRealValue(),waveFormFigureCanvas.getLastPosition());
           }
         // log.info("selection:"+selection);
           log.info("selection: x="+selection.getStart()+",y="+selection.getEnd());
	     //  long starttime=(long)(selection.x*1000/waveFormFigureCanvas.getBaseMemoryPixel());
	     //  long endtime=(long)(selection.y*1000/waveFormFigureCanvas.getBaseMemoryPixel());
           long starttime=selection.getStart();
           long endtime=selection.getEnd();
	       duration=endtime-starttime;
	       log.warn("duration="+duration+",starttime="+starttime+",endtime="+endtime);
	       
	       player=new JavaSoundAudioPlayer();
	       player.setStopper(this);
	       player.setAudioListener(new AudioMove());
	       
	       
	       //TODO call something event
	       //playButton.setEnabled(false);
	       
	      Thread t=new Thread(new PlayingAction(audioFile,starttime,endtime));
	      t.start();
	    }
	
    private class AfterStoppedAction implements Runnable{
        public void run(){
        	//TODO something end play action
            //playButton.setEnabled(true);
           
        }
    }
    
	 public void stop(){
	        log.trace("call stop");
	        stopped=true;
	        shell.getDisplay().asyncExec(new AfterStoppedAction());
	        playMoveSelection=false;
	        /*TODO support multiTime
	        if(multiTimeAudioPlayer!=null){
	            multiTimeAudioPlayer.stop();
	        }
	        */
	    }
	    public boolean isPlayingAudio(){
	        return !stopped;
	    }
	    

	    private class PlayingAction implements Runnable{
	        private File file;
	        private long start;
	        private long end;
	        public PlayingAction(File file,long start,long end){
	            this.file=file;
	            this.start=start;
	            this.end=end;
	        }
	        public void run(){
	            if(stopped==true){
	               
	                    log.info("play-duration:"+(end-start));
	        	        stopped=false;
	        	        try {
                         
	        	        	player.play(file,start,end);
                        } catch (UnsupportedAudioFileException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } catch (LineUnavailableException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
	                    
	              
	                
	            }
	            stop();
	        }
	    }
	    
	    
	    private class MovePositionAction implements Runnable{
	        private long selection;
	        public MovePositionAction(long selection){
	            this.selection=selection;
	        }
	        public void run(){
	           
	            waveFormFigureCanvas.moveCurrentPosition(selection);
	           
	        }
	    }
	    
	    private class AudioMove implements AudioListener{

            /* (non-Javadoc)
             * @see org.jpn.xucker.commons.audio.AudioListener#startPlaying()
             */
            public void startPlaying() {
                playMoveSelection=true;
                //log.info("start-playing");
                shell.getDisplay().syncExec(new MovePositionAction(selection.getStart()));
                log.info("start-playing");
                
                if(selection.getStart()==-1){//when value is -1?
                    //zero start.
                    selection.setStart(0);
                }
                //TODO move collectly
                PlayMove move=new PlayMove(selection.getStart());
                Thread t=new Thread(move);
                t.start();
                
            }

            /* (non-Javadoc)
             * @see org.jpn.xucker.commons.audio.AudioListener#stopPlaying()
             */
            public void stopPlaying() {
                log.trace("stopplaying");
              
                stopped=true;
                playMoveSelection=false;
            }

            /* (non-Javadoc)
             * @see org.jpn.xucker.commons.audio.AudioListener#finishPlaying()
             */
            public void finishPlaying() {
                log.trace("finishplaying");
                stopped=true;
                playMoveSelection=false;
            }
	        
	    }
	    
	

	        /* (non-Javadoc)
	         * @see org.jpn.xucker.commons.audio.AudioStopper#isStopped()
	         */
			
			/**
			 * 
			 * return if
			 */
	        public boolean isStopped() {
	          
	            return stopped; 
	        }

	        /* (non-Javadoc)
	         * @see org.jpn.xucker.commons.audio.AudioStopper#setStopped(boolean)
	         */
	        public void setStopped(boolean arg0) {
	            // TODO Auto-generated method stub
	            
	        }
		    
		
		
		/*
		 * automatic move location sync with playing audio
		 */
	    private class PlayMove extends Thread{
	        int sleeptime=30;
	        long startMillisecond;
	        private boolean canceld=false;
	        public PlayMove(long start){
	        	startMillisecond=start;
	            //log.info("init:"+start);
	        }
	        public void cancel(){
	            canceld=true;
	        }
	        public void run(){
	            
	            long start=System.currentTimeMillis();
	            log.trace("playMoveSelection="+playMoveSelection+","+canceld);
	            while(playMoveSelection && canceld==false){
	            try {
                    Thread.sleep(sleeptime);
                } catch (InterruptedException e) {
                    
                    e.printStackTrace();
                }
               
	            long played=System.currentTimeMillis()-start;
	            log.trace("played:"+played+",duration="+duration);
	            if(played>duration){
	            	//call last time
	            	shell.getDisplay().syncExec(new MovePositionAction(toPosition(duration)));
	                break;
	            }
	            shell.getDisplay().syncExec(new MovePositionAction(toPosition(played)));
	            
	            }
	        }
	        
	        public long toPosition(long time){
	            //log.trace("move"+time);
		        
		        return startMillisecond+time;
		    }
	    }
	    
	    /*
	    public int timeToRealValue(long time){
	        return (int)(time*waveFormFigureCanvas.getBaseMemoryPixel()/1000);
	    }
	    */

		public File getAudioFile() {
			return audioFile;
		}

		public void setAudioFile(File audioFile) {
			this.audioFile = audioFile;
		}
}
